<script setup>
/**
 * 目的：卷帘
 */
import { onMounted, ref } from 'vue';
import img1 from './resources/blueflower.jpg';
import img2 from './resources/blueflower2.jpg';
let gl;
const num = ref(3);
let moveActive = false;
let move;
onMounted(() => {
  // Retrieve <canvas> element
  const canvas = document.getElementById('webgl');
  // Get the rendering context for WebGL
  gl = getWebGLContext(canvas);
  main();
  slider();
});

// MultiTexture.js (c) 2012 matsuda and kanda
// Vertex shader program
const VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute vec2 a_TexCoord;\n' +
  'varying vec2 v_TexCoord;\n' +
  'varying vec4 v_Position;\n' +
  'void main() {\n' +
  '  v_Position = gl_Position = a_Position;\n' +
  '  v_TexCoord = a_TexCoord;\n' +
  '}\n';

// Fragment shader program
const FSHADER_SOURCE = `
#ifdef GL_ES 
precision mediump float; 
#endif 
uniform sampler2D u_Sampler0; 
uniform sampler2D u_Sampler1; 
uniform float u_jlValue; 
uniform int u_jlNum; 
varying vec2 v_TexCoord; 
varying vec4 v_Position; 

const float PI = radians(180.0);
const float PI2 = PI * 2.0;
const float PI05 = PI * 0.5;
const float PI15 = PI * 1.5;

void main() { 
    if(u_jlNum == 1){ 
        if(v_Position.x > u_jlValue){ 
            gl_FragColor = texture2D(u_Sampler0, v_TexCoord);
        }else{ 
            gl_FragColor= texture2D(u_Sampler1, v_TexCoord);
        } 
    }else if(u_jlNum == 2){ 
        if(v_Position.y > u_jlValue){ 
            gl_FragColor = texture2D(u_Sampler0, v_TexCoord);
        }else{ 
            gl_FragColor= texture2D(u_Sampler1, v_TexCoord);
        } 
    }else if(u_jlNum == 3){ 
        float angle = 0.0;   
        float dx = v_Position.x - 0.0;
        float dy = v_Position.y - 0.0;
        if(dx == 0.0){
            if(dy >= 0.0){
                angle = PI05; 
            }else{
                angle = PI15;
            }
        }else{
            float tan = abs(dy/dx);
            angle = atan(tan);
            if(dx >= 0.0){
                if(dy < 0.0){
                    angle = PI2 - angle;
                }
            }else{
                if(dy >= 0.0){
                    angle = PI - angle;
                }else{
                    angle = PI + angle;
                }
            } 
        }
        float curAngle180 = u_jlValue + PI;
        if(curAngle180 > PI2){
            curAngle180 = curAngle180 - PI2;
        }

        if(curAngle180 >= u_jlValue){
            if(angle >= u_jlValue && angle <= curAngle180){ 
                gl_FragColor = texture2D(u_Sampler0, v_TexCoord);
            }else{
                gl_FragColor = texture2D(u_Sampler1, v_TexCoord);
            }
        }else{
            if((angle >= u_jlValue && angle <= PI2)||(angle >= 0.0 && angle <= curAngle180)){ 
                gl_FragColor = texture2D(u_Sampler0, v_TexCoord);
            }else{
                gl_FragColor = texture2D(u_Sampler1, v_TexCoord);
            }
        } 
    }else {
        gl_FragColor = texture2D(u_Sampler0, v_TexCoord);
    };
}`;

function main() {
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }

  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }

  // Set the vertex information
  const n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the vertex information');
    return;
  }

  // Specify the color for clearing <canvas>
  gl.clearColor(0.0, 0.0, 0.0, 1.0);

  // Set texture
  if (!initTextures(gl, n)) {
    console.log('Failed to intialize the texture.');
    return;
  }
}

function initVertexBuffers(gl) {
  const verticesTexCoords = new Float32Array([
    // Vertex coordinate, Texture coordinate
    -1.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
    1.0, 0.0,
  ]);
  const n = 4; // The number of vertices

  // Create a buffer object
  const vertexTexCoordBuffer = gl.createBuffer();
  if (!vertexTexCoordBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  // Write the positions of vertices to a vertex shader
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

  const FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
  //Get the storage location of a_Position, assign and enable buffer
  const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
  gl.enableVertexAttribArray(a_Position); // Enable the assignment of the buffer object

  // Get the storage location of a_TexCoord
  const a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
  if (a_TexCoord < 0) {
    console.log('Failed to get the storage location of a_TexCoord');
    return -1;
  }
  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
  gl.enableVertexAttribArray(a_TexCoord); // Enable the buffer assignment

  return n;
}

function initTextures(gl, n) {
  // Create a texture object
  const texture0 = gl.createTexture();
  const texture1 = gl.createTexture();
  if (!texture0 || !texture1) {
    console.log('Failed to create the texture object');
    return false;
  }

  // Get the storage location of u_Sampler0 and u_Sampler1
  const u_Sampler0 = gl.getUniformLocation(gl.program, 'u_Sampler0');
  const u_Sampler1 = gl.getUniformLocation(gl.program, 'u_Sampler1');
  if (!u_Sampler0 || !u_Sampler1) {
    console.log('Failed to get the storage location of u_Sampler');
    return false;
  }

  // Create the image object
  const image0 = new Image();
  const image1 = new Image();
  if (!image0 || !image1) {
    console.log('Failed to create the image object');
    return false;
  }
  // Register the event handler to be called when image loading is completed
  image0.onload = function () {
    loadTexture(gl, n, texture0, u_Sampler0, image0, 0);
  };
  image1.onload = function () {
    loadTexture(gl, n, texture1, u_Sampler1, image1, 1);
  };
  // Tell the browser to load an Image
  image0.src = img1;
  image1.src = img2;

  return true;
}
// Specify whether the texture unit is ready to use
let g_texUnit0 = false,
  g_texUnit1 = false;
function loadTexture(gl, n, texture, u_Sampler, image, texUnit) {
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // Flip the image's y-axis
  // Make the texture unit active
  if (texUnit == 0) {
    gl.activeTexture(gl.TEXTURE0);
    g_texUnit0 = true;
  } else {
    gl.activeTexture(gl.TEXTURE1);
    g_texUnit1 = true;
  }
  // Bind the texture object to the target
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Set texture parameters
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  // Set the image to texture
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

  gl.uniform1i(u_Sampler, texUnit); // Pass the texure unit to u_Sampler

  // Clear <canvas>
  gl.clear(gl.COLOR_BUFFER_BIT);

  if (g_texUnit0 && g_texUnit1) {
    const u_jlValue = gl.getUniformLocation(gl.program, 'u_jlValue');
    gl.uniform1f(u_jlValue, num.value === 3 ? Math.PI * 0.25 : 0.0);
    const u_jlNum = gl.getUniformLocation(gl.program, 'u_jlNum');
    gl.uniform1i(u_jlNum, num.value);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n); // Draw the rectangle
  }
}

// 卷帘类型切换
function roller(type) {
  num.value = type;
  slider();
  reDraw(num.value === 3 ? Math.PI * 0.25 : 0.0);
}

// 设置卷帘
function slider() {
  const type = num.value;
  const slider = document.getElementById('slider');

  if (move) {
    window.removeEventListener('mousemove', move);
  }

  if (type === 1) {
    slider.style.left = '50%';
    slider.style.top = '0';
    slider.style.width = '5px';
    slider.style.height = '100%';
    slider.style.cursor = 'ew-resize';
    slider.style.transform = `rotate(0deg)`;
    move = (movement) => {
      if (!moveActive) {
        return;
      }
      const parentE = slider.parentElement.parentElement;
      const offsetX = movement.x - parentE.offsetLeft;
      const offsetWidth = parentE.offsetWidth;
      const splitPosition = offsetX / offsetWidth;
      const webglX = splitPosition * 2 - 1;
      if (webglX > 1) {
        slider.style.left = offsetWidth - 5 + 'px';
      } else if (webglX < -1) {
        slider.style.left = 0 + 'px';
      } else {
        slider.style.left = offsetX + 'px';
      }
      //   slider.style.left = 100 * splitPosition + '%';
      reDraw(webglX);
    };
  } else if (type === 2) {
    slider.style.left = '0';
    slider.style.top = '50%';
    slider.style.width = '100%';
    slider.style.height = '5px';
    slider.style.cursor = 'ns-resize';
    slider.style.transform = `rotate(0deg)`;
    move = (movement) => {
      if (!moveActive) {
        return;
      }

      const parentE = slider.parentElement.parentElement;
      const offsetY = movement.y - parentE.offsetTop;
      const offsetHeight = parentE.offsetHeight;
      let splitPosition = offsetY / offsetHeight;
      if (splitPosition < 0) {
        splitPosition = 0;
        slider.style.top = 0 + 'px';
      } else if (splitPosition > 1) {
        splitPosition = 1;
        slider.style.top = offsetHeight - 5 + 'px';
      } else {
        slider.style.top = offsetY + 'px';
      }
      const webglY = 1 - splitPosition * 2;
      reDraw(webglY);
    };
  } else {
    // 获取旋转角，传递旋转角度
    slider.style.left = '50%';
    slider.style.width = '5px';
    slider.style.top = '-450%';
    slider.style.height = '1000%';
    slider.style.cursor = 'auto';
    slider.style.transform = `rotate(45deg)`;
    // this.CUR_ANGLE = Math.PI * 0.5;
    const parentE = slider.parentElement.parentElement;
    const offsetHeight = parentE.offsetHeight;
    const offsetWidth = parentE.offsetWidth;

    const PI2 = Math.PI * 2;
    let deg = Math.PI * 0.5;

    move = (e) => {
      if (!moveActive) {
        return;
      }
      const x = offsetWidth / 2;
      const y = offsetHeight / 2;
      const x1 = e.x - parentE.offsetLeft;
      const y1 = e.y - parentE.offsetTop;
      deg = Math.atan2(y1 - y, x1 - x) * (180 / Math.PI) - 90;

      slider.style.transform = `rotate(${deg - 180}deg)`;
      if (-90 <= deg <= 90) {
        deg = ((-deg + 270) / 180) * Math.PI;
      } else {
        deg = (-(deg + 90) / 180) * Math.PI;
      }
      if (deg < 0) {
        deg = PI2 - deg;
      }
      if (deg > PI2) {
        deg = deg - PI2;
      }
      reDraw(deg);
      //   this.CUR_ANGLE = deg;
    };
  }

  slider.onmousedown = function () {
    moveActive = true;
  };
  window.addEventListener('mousemove', move);
  window.addEventListener('mouseup', () => {
    moveActive = false;
  });
}

//重绘
function reDraw(x) {
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear color and depth buffers
  const u_jlValue = gl.getUniformLocation(gl.program, 'u_jlValue');
  gl.uniform1f(u_jlValue, x);
  const u_jlNum = gl.getUniformLocation(gl.program, 'u_jlNum');
  gl.uniform1i(u_jlNum, num.value);
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // Draw the rectangle
}
</script>


<template>
  <div id="JL">
    <canvas id="webgl">
      Please use a browser that supports "canvas"
    </canvas>
    <div id="Roller">
      <div id="slider">
      </div>
      <div class='tool'>
        <section :class="num === 1 ? 'active' : null">
          <span @click="() => roller(1)">
            左右
          </span>
        </section>
        <section :class="num === 2 ? 'active' : null">
          <span @click="() => roller(2)">
            上下
          </span>
        </section>
        <section :class="num === 3 ? 'active' : null">
          <span @click="() => roller(3)">
            倾斜
          </span>
        </section>
        <!-- <template v-if="num === 1">
          <section :class="isAuto ? 'active' : null">
            <span @click="(e) => autoCtrl(!isAuto)">
              播放
            </span>
          </section>
        </template> -->
      </div>
    </div>
  </div>

</template>


<style lang="scss">
#JL {
  width: 800px;
  height: 800px;
  position: absolute;
  overflow: hidden;
  top: calc(50% - 400px);
  left: calc(50% - 400px);
  #webgl {
    width: 100%;
    height: 100%;
  }
  #Roller {
    #slider {
      position: absolute;
      left: 50%;
      top: 0px;
      background-color: #d3d3d3;
      width: 5px;
      height: 200%;
      z-index: 1;
      cursor: ew-resize;
    }
    .active {
      color: #66defaff;
    }

    .tool {
      padding: 0 10px;
      width: 150px;
      z-index: 2;
      height: 30px;
      position: absolute;
      background: #0e0c0ca8;
      color: #fff;
      border-radius: 10px;
      top: 20px;
      margin: 10px;
      display: grid;
      align-items: center;
      grid-template-columns: 1fr 1fr 1fr;
      justify-items: center;
      right: 20px;
      font-size: 15px;
      section {
        cursor: pointer;
      }
    }
    .tool2 {
      @extend .tool;
      width: 180px;
      grid-template-columns: 1fr 1fr 1fr 1fr;
    }
  }
}
</style>